import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.TreeMap;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import com.thoughtworks.xstream.XStream;


public class DictionaryWSD extends DefaultHandler {

  static boolean train = false;
  /**
   * @param args
   */
  public static void main(String[] args) {
    try {

      File wsdObjFile = new File("data/objects/wsdObj");
      File trainObjFile = new File("data/objects/training");
      XStream xstream = new XStream();

      if(train) {
        String senseInvFile = "data/EnglishLS/EnglishLS.dictionary.mapping.xml";
        WSD wsdObject = new WSD(senseInvFile);
        System.out.println("Dictionary loaded successfully");

        File trainFile = new File("data"+File.separator+"EnglishLS"+File.separator+"EnglishLS.train");
        File posTrain = new File("data"+File.separator+"EnglishLS"+File.separator+"EnglishLS.train.pos");
        WSD.posTag(trainFile, posTrain);
        System.out.println("trained file with pos tags:" + posTrain);
        Training trainModel = new Training(posTrain.getAbsolutePath());
        System.out.println("Model trained successfully");

        xstream.toXML(wsdObject, new FileWriter(wsdObjFile));
        xstream.toXML(trainModel, new FileWriter(trainObjFile));
      }
      
      WSD wsdObj = (WSD)xstream.fromXML(new FileReader(wsdObjFile));
      Training trainObj = (Training)xstream.fromXML(new FileReader(trainObjFile));
      
      String outFile = "data/scorer/Coll.Dict.Test.output";
      File testFile = new File("data"+File.separator+"EnglishLS"+File.separator+"EnglishLS.test");
//      File posTest = new File("data"+File.separator+"EnglishLS"+File.separator+"EnglishLS.test.pos");
//      WSD.posTag(testFile, posTest);
//      System.out.println("test file with pos tags:" + posTest);
      
      SenseInventory senseInv = wsdObj.getSenseInv();

      TestingDictionary testingDict = new TestingDictionary(testFile.getAbsolutePath(), outFile, trainObj, senseInv, wsdObj);
      
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  // stores dictionary in the format of "main word", {senseID, gloss}
  HashMap<String, HashMap<Integer, String>> dictionary = new HashMap<String, HashMap<Integer,String>>();

  private File outFile;

  private File dictFile;

  private File tempFile;

  // this would read the dictFile 
  // and dump the dictionary created in outFile in Object format.
  public DictionaryWSD(File dictFile, File tempFile, File outFile) {
    try {

      this.dictFile = dictFile;
      this.tempFile = tempFile;
      this.outFile = outFile;

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void startTraining() {
    try {
      format(dictFile, tempFile);

      XMLReader xmlr = XMLReaderFactory.createXMLReader();
      xmlr.setContentHandler(this);
      xmlr.setErrorHandler(this);

      xmlr.parse(new InputSource(new FileReader(tempFile)));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  private void format(File dictFile, File outFile) {
    try {
      BufferedReader reader = new BufferedReader(new FileReader(dictFile));
      BufferedWriter writer = new BufferedWriter(new FileWriter(outFile)); 
      String str;
      while((str = reader.readLine()) != null) {
        if(str.startsWith("<lexelt"))
          writer.write(str + "\n");
        else if(str.startsWith("<sense")) {
          int glossIdx = str.indexOf("gloss=\"") + "gloss=\"".length();
          String replaceAll = str.substring(glossIdx, str.length() - 3).replaceAll("\"", " ");
          str = str.substring(0, glossIdx) + replaceAll + "\"/>";
          writer.write(str + "\n");
        }
      }

      writer.flush();
      writer.close();

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  String currWord;
  HashMap<Integer, String> senseGlossMap;
  @Override
  public void startElement(String uri, String localName, String qName,
      Attributes attributes) throws SAXException {
    if(qName.equalsIgnoreCase("lexelt")) {
      currWord = attributes.getValue("item");
      senseGlossMap = new HashMap<Integer, String>();
      dictionary.put(attributes.getValue("item"), new HashMap<Integer, String>());
    }
    else if(qName.equalsIgnoreCase("sense")) {
      senseGlossMap.put(Integer.parseInt(attributes.getValue("id")), 
          attributes.getValue("gloss"));
    }
  }

  @Override
  public void endElement(String uri, String localName, String qName)
  throws SAXException {
    if(qName.equalsIgnoreCase("lexelt")) {
      dictionary.put(currWord, senseGlossMap);
    }
  }

  @Override
  public void endDocument() throws SAXException {
    try {
      XStream xstream = new XStream();
      xstream.toXML(dictionary, new BufferedWriter(new FileWriter(outFile)));
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
